package cn.hbads.support.structure.result;

import java.util.function.BiFunction;
import java.util.function.Consumer;
import java.util.function.Function;

/**
 * <b>操作结果封装对象<b/>
 *
 * @author yvvb
 * @date 2025/5/4
 */
public class OpResult<E> {

    private final boolean isSuccess;
    private final E failedModel;
    private final Throwable cause;

    private OpResult(boolean isSuccess, E failedModel, Throwable cause) {
        this.isSuccess = isSuccess;
        this.failedModel = failedModel;
        this.cause = cause;
    }

    public static <E> OpResult<E> fail(E failedModel) {
        return new OpResult<>(false, failedModel, null);
    }

    public static <E> OpResult<E> fail(E failedModel, Throwable cause) {
        return new OpResult<>(false, failedModel, cause);
    }

    public static <E> OpResult<E> success() {
        return new OpResult<>(true, null, null);
    }

    public void unwrapped() throws Throwable {
        if (!this.isSuccess) {
            throw cause;
        }
    }

    public <X extends Throwable> void unwrapped(Function<E, X> errorMsgFunction) throws X {
        if (!this.isSuccess) {
            throw errorMsgFunction.apply(failedModel);
        }
    }

    public <X extends Throwable> void orElseThrow(BiFunction<E, Throwable, X> errorMsgFunction) throws X {
        if (!this.isSuccess) {
            throw errorMsgFunction.apply(failedModel, cause);
        }
    }

    public boolean isSuccess() {
        return isSuccess;
    }

    public void ifSuccess(Runnable runnable) {
        if (isSuccess) {
            runnable.run();
        }
    }

    public void ifFail(Runnable runnable) {
        if (!isSuccess) {
            runnable.run();
        }
    }

    public void ifFail(Consumer<E> consumer) {
        if (!isSuccess) {
            consumer.accept(failedModel);
        }
    }
}
